package cn.edu.sdjzu.knoverse.repository;

import cn.edu.sdjzu.knoverse.model.entity.kg.CourseNode;
import cn.edu.sdjzu.knoverse.model.entity.kg.UserNode;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import org.springframework.data.neo4j.repository.query.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Set;

@Repository
public interface CourseRepository extends Neo4jRepository<CourseNode, Long> {

    /**
     * 条件查询课程
     * @param name 课程名称
     * @param code 课程编码
     * @param description 课程描述
     * @param pageable 分页参数
     * @return 符合条件的课程分页数据
     */
    @Query(value = "MATCH (c:Course) " +
            "WHERE " +
            "($name IS NULL OR c.name CONTAINS $name) AND " +
            "($code IS NULL OR c.code CONTAINS $code) AND " +
            "($description IS NULL OR c.description CONTAINS $description) " +
            "RETURN c",
            countQuery = "MATCH (c:Course) " +
                    "WHERE " +
                    "($name IS NULL OR c.name CONTAINS $name) AND " +
                    "($code IS NULL OR c.code CONTAINS $code) AND " +
                    "($description IS NULL OR c.description CONTAINS $description) " +
                    "RETURN count(c)")
    Page<CourseNode> findByConditions(@Param("name") String name, 
                                     @Param("code") String code, 
                                     @Param("description") String description, 
                                     Pageable pageable);

    // 批量创建教师与课程的关系
    @Query("MATCH (u:User) WHERE u.userId IN $userIds " +
            "MATCH (c:Course) WHERE c.nodeId = $courseId " +
            "MERGE (u)-[r:TEACH]->(c)")
    void createTeachRelationships(Long courseId, List<Long> userIds);

    // 删除所有教师与课程的关系
    @Query("MATCH (u:User)-[r:TEACH]->(c:Course) WHERE c.nodeId = $courseId DELETE r")
    void deleteTeachRelationships(Long courseId);
    
    /**
     * 删除课程的所有前置课程关系
     * @param courseId 课程ID
     */
    @Query("MATCH (c1:Course)-[r:PRE_COURSE]->(c2:Course) WHERE c1.nodeId = $courseId DELETE r")
    void deletePreCourseRelationships(Long courseId);
    
    /**
     * 创建前置课程关系
     * @param courseId 当前课程ID
     * @param preCourseId 前置课程ID
     * @param name 关系名称
     * @param description 关系描述
     */
    @Query("MATCH (c1:Course) WHERE c1.nodeId = $courseId " +
           "MATCH (c2:Course) WHERE c2.nodeId = $preCourseId " +
           "MERGE (c1)-[r:PRE_COURSE {name: $name, description: $description}]->(c2)")
    void createPreCourseRelationship(Long courseId, Long preCourseId, String name, String description);
    
    /**
     * 获取课程的所有前置课程
     * @param courseId 课程ID
     * @return 前置课程列表
     */
    @Query("MATCH (c1:Course)-[r:PRE_COURSE]->(c2:Course) WHERE c1.nodeId = $courseId RETURN c2")
    Set<CourseNode> findPreCourses(Long courseId);
    
    /**
     * 检查两门课程之间是否存在前置课程关系
     * @param courseId 课程ID
     * @param preCourseId 前置课程ID
     * @return 存在返回true，否则返回false
     */
    @Query("MATCH (c1:Course) WHERE c1.nodeId = $courseId " +
           "MATCH (c2:Course) WHERE c2.nodeId = $preCourseId " +
           "RETURN EXISTS((c1)-[:PRE_COURSE]->(c2))")
    boolean existsPreCourseRelationship(Long courseId, Long preCourseId);
    
    /**
     * 检查添加前置课程关系后是否会导致循环依赖
     * 使用Neo4j路径查询检查是否存在从前置课程到当前课程的路径，如果存在则表示有循环依赖
     * 
     * @param courseId 当前课程ID
     * @param preCourseId 前置课程ID
     * @return 如果添加这个关系会导致循环依赖，返回true；否则返回false
     */
    @Query("MATCH (c1:Course), (c2:Course) " +
           "WHERE c1.nodeId = $courseId AND c2.nodeId = $preCourseId " +
           "RETURN EXISTS( " +
           "  (c2)-[:PRE_COURSE*1..]->(c1) " +
           ")")
    boolean wouldCreateCyclicDependency(Long courseId, Long preCourseId);

    /**
     * 根据教师ID查询所教授的课程
     * @param teacherId 教师ID
     * @return 课程列表
     */
    @Query("MATCH (u:User)-[:TEACH]->(c:Course) WHERE u.userId = $teacherId RETURN c")
    List<CourseNode> findCoursesByTeacherId(Long teacherId);
} 